package com.deng.eventflow.core.tmf;

import com.deng.eventflow.core.Pullable;
import com.deng.eventflow.core.Pushable;
import com.deng.eventflow.core.UniformProcessor;

import java.util.ArrayDeque;
import java.util.Queue;

public class Fork extends UniformProcessor {
    public Fork(int out_arity)
    {
        super(1, out_arity);
    }

    public Fork()
    {
        this(2);
    }

    @Override
    public Fork duplicate(boolean with_state)
    {
        return new Fork(getOutputArity());
    }

    @Override
    protected boolean compute(Object[] inputs, Object[] outputs)
    {
        int arity = getOutputArity();
        for (int i = 0; i < arity; i++)
        {
            outputs[i] = inputs[0];
        }
        return true;
    }

    /**
     * Creates a copy of the current fork with a greater arity
     *
     * @param out_arity
     *          The desired arity for the output fork
     */
    @SuppressWarnings("unchecked")
    public void extendOutputArity(int out_arity)
    {
        m_outputArray = new Object[out_arity];
        m_outputQueues = new Queue[out_arity];
        Pullable[] new_out_pullables = new Pullable[out_arity];
        for (int i = 0; i < m_outputArity; i++)
        {
            new_out_pullables[i] = m_outputPullables[i];
        }
        m_outputPullables = new_out_pullables;
        m_outputArity = out_arity;
        for (int i = 0; i < m_outputArity; i++)
        {
            m_outputQueues[i] = new ArrayDeque<Object>();
        }
        Pushable[] out_pushables = new Pushable[out_arity];
        for (int i = 0; i < m_outputPushables.length; i++)
        {
            out_pushables[i] = m_outputPushables[i];
        }
        m_outputPushables = out_pushables;
    }

    /**
     * @since 0.10.2
     */
    public Object printState()
    {
        return getOutputArity();
    }

    /**
     * @since 0.10.2
     */
    @Override
    public Fork readState(Object o)
    {
        return new Fork(((Number) o).intValue());
    }
}
